package com.ray.wms.api;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.base.service.compose.GoodsService;
import com.ray.base.table.vo.material.model.MaterialModelVO;
import com.ray.business.check.OrderCheck;
import com.ray.business.service.ProdOrderService;
import com.ray.business.table.entity.ProdOrder;
import com.ray.business.table.entity.ProdOrderStep;
import com.ray.common.check.AbstractCheck;
import com.ray.system.builder.CommonPageBuilder;
import com.ray.wms.builder.GoodsBuilder;
import com.ray.wms.builder.GoodsVOBuilder;
import com.ray.wms.check.StockDetailCheck;
import com.ray.wms.enums.InOutTypeEnum;
import com.ray.wms.service.WmsWarehouseService;
import com.ray.wms.service.WmsWarehouseStockDetailService;
import com.ray.wms.service.WmsWarehouseStockLogService;
import com.ray.wms.service.WmsWarehouseStockService;
import com.ray.wms.service.compose.InService;
import com.ray.wms.service.compose.OutService;
import com.ray.wms.table.dto.StockQueryDTO;
import com.ray.wms.table.entity.WmsWarehouse;
import com.ray.wms.table.entity.WmsWarehouseStock;
import com.ray.wms.table.entity.WmsWarehouseStockDetail;
import com.ray.wms.table.entity.WmsWarehouseStockLog;
import com.ray.wms.table.params.DetailChangeParams;
import com.ray.wms.table.params.WareHouseChangeParams;
import com.ray.wms.table.params.order.StockQueryParams;
import com.ray.wms.table.vo.order.GoodsVO;
import com.ray.woodencreate.beans.CommonValue;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import com.ray.woodencreate.page.CommonPage;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import com.ray.woodencreate.util.LogInUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 出库相关服务
 * @Class: InApi
 * @Package com.ray.wms.api
 * @date 2020/6/3 15:09
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
@Service
public class StockApi {

    @Autowired
    private WmsWarehouseStockService wmsWarehouseStockService;
    @Autowired
    private WmsWarehouseStockDetailService wmsWarehouseStockDetailService;
    @Autowired
    private WmsWarehouseStockLogService wmsWarehouseStockLogService;
    @Autowired
    private WmsWarehouseService wmsWarehouseService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ProdOrderService prodOrderService;
    @Autowired
    private InService inService;
    @Autowired
    private OutService outService;

    /**
     * 查询库存详情
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<GoodsVO>> queryStocks(CommonPage<StockQueryParams, Page<GoodsVO>> queryParams) {
        LoginUser loginUser = LogInUserUtil.get();
        Map<String, MaterialModelVO> modelMap = new HashMap<>();
        Map<String, WmsWarehouse> wmsWarehouseMap = new HashMap<>();
        CommonPageBuilder<StockQueryDTO, WmsWarehouseStock> commonPageBuilder = new CommonPageBuilder<>(StockQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<WmsWarehouseStock> page = wmsWarehouseStockService.page(commonPageBuilder.bulid(), loginUser);
        List<WmsWarehouseStock> records = page.getRecords();
        //结果对象
        IPage<GoodsVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(records)) {
            pageList.setRecords(records.stream().map(warehouseStock -> {
                GoodsVOBuilder goodsBuilder = new GoodsVOBuilder();
                MaterialModelVO materialModel = modelMap.get(warehouseStock.getGoodsCode());
                //库存对象转换
                if (ObjectUtil.isNull(materialModel)) {
                    materialModel = goodsService.queryGoodsByCode(warehouseStock.getGoodsCode(), loginUser);
                    modelMap.put(warehouseStock.getGoodsCode(), materialModel);
                }
                //查询仓库信息
                WmsWarehouse wmsWarehouse = wmsWarehouseMap.get(warehouseStock.getWarehouseCode());
                if (ObjectUtil.isEmpty(wmsWarehouse)) {
                    wmsWarehouse = wmsWarehouseService.queryWarehouseByWarehouseCode(warehouseStock.getWarehouseCode(), loginUser);
                    wmsWarehouseMap.put(wmsWarehouse.getWarehouseCode(), wmsWarehouse);
                }
                goodsBuilder.append(materialModel).append(wmsWarehouse).append(warehouseStock)
                        .appendTime(warehouseStock.getCreateTime()).appendUser(warehouseStock.getCreateUserName());
                return goodsBuilder.bulid();
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }


    /**
     * 查询库存明细详情
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<GoodsVO>> queryStockDetails(CommonPage<StockQueryParams, Page<GoodsVO>> queryParams) {
        LoginUser loginUser = LogInUserUtil.get();
        Map<String, MaterialModelVO> modelMap = new HashMap<>();
        Map<String, WmsWarehouse> wmsWarehouseMap = new HashMap<>();
        CommonPageBuilder<StockQueryDTO, WmsWarehouseStockDetail> commonPageBuilder = new CommonPageBuilder<>(StockQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<WmsWarehouseStockDetail> page = wmsWarehouseStockDetailService.page(commonPageBuilder.bulid(), loginUser);
        List<WmsWarehouseStockDetail> records = page.getRecords();
        //结果对象
        IPage<GoodsVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(records)) {
            pageList.setRecords(records.stream().map(warehouseStockDetail -> {
                GoodsVOBuilder goodsBuilder = new GoodsVOBuilder();
                MaterialModelVO materialModel = modelMap.get(warehouseStockDetail.getGoodsCode());
                //库存详情对象转换
                if (ObjectUtil.isNull(materialModel)) {
                    materialModel = goodsService.queryGoodsByCode(warehouseStockDetail.getGoodsCode(), loginUser);
                    modelMap.put(warehouseStockDetail.getGoodsCode(), materialModel);
                }
                //查询仓库信息
                WmsWarehouse wmsWarehouse = wmsWarehouseMap.get(warehouseStockDetail.getWarehouseCode());
                if (ObjectUtil.isEmpty(wmsWarehouse)) {
                    wmsWarehouse = wmsWarehouseService.queryWarehouseByWarehouseCode(warehouseStockDetail.getWarehouseCode(), loginUser);
                    wmsWarehouseMap.put(wmsWarehouse.getWarehouseCode(), wmsWarehouse);
                }
                goodsBuilder.append(materialModel).append(wmsWarehouse).append(warehouseStockDetail)
                        .appendTime(warehouseStockDetail.getCreateTime()).appendUser(warehouseStockDetail.getCreateUserName());
                return goodsBuilder.bulid();
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }


    /**
     * 查询库存明细详情
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<GoodsVO>> queryStockLogs(CommonPage<StockQueryParams, Page<GoodsVO>> queryParams) {
        LoginUser loginUser = LogInUserUtil.get();
        Map<String, MaterialModelVO> modelMap = new HashMap<>();
        Map<String, WmsWarehouse> wmsWarehouseMap = new HashMap<>();
        CommonPageBuilder<StockQueryDTO, WmsWarehouseStockLog> commonPageBuilder = new CommonPageBuilder<>(StockQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<WmsWarehouseStockLog> page = wmsWarehouseStockLogService.page(commonPageBuilder.bulid(), loginUser);
        List<WmsWarehouseStockLog> records = page.getRecords();
        //结果对象
        IPage<GoodsVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(records)) {
            pageList.setRecords(records.stream().map(warehouseStockLog -> {
                GoodsVOBuilder goodsBuilder = new GoodsVOBuilder();
                MaterialModelVO materialModel = modelMap.get(warehouseStockLog.getGoodsCode());
                //库存日志对象转换
                if (ObjectUtil.isNull(materialModel)) {
                    materialModel = goodsService.queryGoodsByCode(warehouseStockLog.getGoodsCode(), loginUser);
                    modelMap.put(warehouseStockLog.getGoodsCode(), materialModel);
                }
                //查询仓库信息
                WmsWarehouse wmsWarehouse = wmsWarehouseMap.get(warehouseStockLog.getWarehouseCode());
                if (ObjectUtil.isEmpty(wmsWarehouse)) {
                    wmsWarehouse = wmsWarehouseService.queryWarehouseByWarehouseCode(warehouseStockLog.getWarehouseCode(), loginUser);
                    wmsWarehouseMap.put(wmsWarehouse.getWarehouseCode(), wmsWarehouse);
                }
                goodsBuilder.append(materialModel).append(wmsWarehouse).append(warehouseStockLog)
                        .appendTime(warehouseStockLog.getCreateTime()).appendUser(warehouseStockLog.getCreateUserName());
                return goodsBuilder.bulid();
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }

    /**
     * 明细记录变更
     *
     * @param changeParams
     * @return
     */
    public Result<String> detailChange(DetailChangeParams changeParams) {
        LoginUser loginUser = LogInUserUtil.get();

        if(StrUtil.isBlank(changeParams.getNewOrderNo())){
            changeParams.setNewOrderNo(CommonValue.DEFAULT_ZERO);
        }
        //查询记录是否存在
        WmsWarehouseStockDetail detail = wmsWarehouseStockDetailService.queryByCode(changeParams.getCode(), loginUser);
        new StockDetailCheck(detail).checkNull("记录不存在").checkQuantity(changeParams.getQuantity(),"更改数量不足");
        if(StrUtil.equals(detail.getBusinessOrderNo(),changeParams.getNewOrderNo())){
            log.info("变更订单一致:{}",changeParams.getNewOrderNo());
            throw BusinessExceptionFactory.newException("变更订单一致");
        }
        if(StrUtil.isNotBlank(detail.getBusinessOrderNo())&& !StrUtil.equals(CommonValue.DEFAULT_ZERO,detail.getBusinessOrderNo())){
            ProdOrder oldOrder = prodOrderService.queryOrderByOrderCode(detail.getBusinessOrderNo(),loginUser);
            new OrderCheck(oldOrder).checkNull("订单数据异常").checkFinish("订单未完成不能变更");
        }
        //不是默认订单
        if(!StrUtil.equals(changeParams.getNewOrderNo(),CommonValue.DEFAULT_ZERO)){
            ProdOrder newOrder = prodOrderService.queryOrderByOrderCode(changeParams.getNewOrderNo(),loginUser);
            new OrderCheck(newOrder).checkNull("变更订单不存在");
        }

       //出库
        GoodsBuilder outGoodsBuilder = new GoodsBuilder();
        outGoodsBuilder.append(detail).cancel().appendWarehouseCode(detail.getWarehouseCode()).appendOrderNo(detail.getBusinessOrderNo())
                .appendInOutType(InOutTypeEnum.OUT.getValue()).appendQuantity(changeParams.getQuantity()).cancel();
        outService.orderOut(outGoodsBuilder.bulid(),loginUser);
        //入库
        GoodsBuilder inGoodsBuilder = new GoodsBuilder();
        inGoodsBuilder.append(detail).appendWarehouseCode(detail.getWarehouseCode()).appendOrderNo(changeParams.getNewOrderNo())
                .appendInOutType(InOutTypeEnum.IN.getValue()).appendQuantity(changeParams.getQuantity());
        inService.orderIn(inGoodsBuilder.bulid(),loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, changeParams.getCode());
    }



    /**
     * 仓库明细记录变更
     *
     * @param changeParams
     * @return
     */
    public Result<String> wareHouseChange(WareHouseChangeParams changeParams) {
        LoginUser loginUser = LogInUserUtil.get();

        //查询记录是否存在
        WmsWarehouseStockDetail detail = wmsWarehouseStockDetailService.queryByCode(changeParams.getCode(), loginUser);
        new StockDetailCheck(detail).checkNull("记录不存在").checkQuantity(changeParams.getQuantity(),"更改数量不足");
        if(StrUtil.equals(detail.getWarehouseCode(),changeParams.getWarehouseCode())){
            log.info("变更仓库一致:{}",changeParams.getWarehouseCode());
            throw BusinessExceptionFactory.newException("变更仓库一致");
        }

        //出库
        GoodsBuilder outGoodsBuilder = new GoodsBuilder();
        outGoodsBuilder.append(detail).appendWarehouseCode(detail.getWarehouseCode()).appendOrderNo(detail.getBusinessOrderNo())
                .appendInOutType(InOutTypeEnum.OUT.getValue()).appendQuantity(changeParams.getQuantity()).cancel();
        outService.orderOut(outGoodsBuilder.bulid(),loginUser);
        //入库
        GoodsBuilder inGoodsBuilder = new GoodsBuilder();
        inGoodsBuilder.append(detail).appendWarehouseCode(changeParams.getWarehouseCode()).appendOrderNo(detail.getBusinessOrderNo())
                .appendInOutType(InOutTypeEnum.IN.getValue()).appendQuantity(changeParams.getQuantity());
        inService.orderIn(inGoodsBuilder.bulid(),loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, changeParams.getCode());
    }


}
